package com.enjoyor.soa.traffic.server.tsms.handler;

import com.enjoyor.soa.traffic.core.tsms.domain.*;
import com.enjoyor.soa.traffic.core.tsms.service.IRouteInfoService;
import com.enjoyor.soa.traffic.core.tsms.util.SpringContextUtil;
import com.enjoyor.soa.traffic.server.tsms.common.RehearseGlobal;
import com.enjoyor.soa.traffic.server.tsms.dubbo.impl.DubboSchemeRehearseService;
import com.enjoyor.soa.traffic.server.tsms.dubbo.impl.DubboServerPushServiceImpl;
import com.enjoyor.soa.traffic.server.tsms.helper.RouteClashHelper;
import com.enjoyor.soa.traffic.server.tsms.helper.RouteHandleHelper;
import com.enjoyor.soa.traffic.util.handler.BasicMsgHandler;

import java.util.*;

/**
 * 预演冲突检测
 */
public class RehearseClashHandler extends BasicMsgHandler<Map<String,Object>> {
	private RehearseClashHandler() {
		super(1000,"预演冲突检测");
	}

	private static RehearseClashHandler single;

	public static RehearseClashHandler getInstance() {
		if (single == null) {
			synchronized (RehearseClashHandler.class) {
				if (single == null) {
					single = new RehearseClashHandler();
					single.setMultiProcess(5, 30, 1);
				}
			}
		}
		return single;
	}

	@Override
	protected boolean task(int taskTimes){
        return true;
    }

	private DubboServerPushServiceImpl dubboServerPushServiceImpl;
	public DubboServerPushServiceImpl getServerPushServiceImpl(){
		if(dubboServerPushServiceImpl==null){
			dubboServerPushServiceImpl = (DubboServerPushServiceImpl) SpringContextUtil.getBean(DubboServerPushServiceImpl.class);
		}
		return dubboServerPushServiceImpl;
	}
	private IRouteInfoService iRouteInfoService;
	public IRouteInfoService getRouteInfoService(){
		if(iRouteInfoService==null){
			iRouteInfoService = (IRouteInfoService) SpringContextUtil.getBean(IRouteInfoService.class);
		}
		return iRouteInfoService;
	}

	@SuppressWarnings("unchecked")
	@Override
	protected boolean process(Map<String,Object> msg) {
		long minBeginLong = 9999999999999l; //最小开始时间戳
		long maxEndLong = 0;//最大结束时间戳
		List<Map<String, Object>> taskRouteList = new ArrayList<Map<String,Object>>();
		String browserId = (String)msg.get("browserId");
		String executeDate = (String)msg.get("executeDate");
		List<SchemeInfo> schemeList = (List<SchemeInfo>)msg.get("schemeList");
		int routeSplitTime = DubboSchemeRehearseService.routeSplitTime;
		int timeNum = DubboSchemeRehearseService.timeNum;//冲突校验的时间间隔数
		int clashDistance = DubboSchemeRehearseService.clashDistance;//车队冲突距离
		//DubboServerPushServiceImpl dubboServerPushServiceImpl = (DubboServerPushServiceImpl)msg.get("dubboServerPushServiceImpl");
		//IRouteInfoService iRouteInfoService = (IRouteInfoService)msg.get("iRouteInfoService");
		boolean isDetail = (boolean)msg.get("isDetail");
		try {
			com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
			Map<String, Map<String, Object>> clashMap = new HashMap<String, Map<String, Object>>();
			String poolKey = browserId+"_"+executeDate;
			Map<String, Object> rehearseMap = RehearseGlobal.RehearseDataPool.get(poolKey);
			//if(false) {
			if(isDetail && rehearseMap != null && !rehearseMap.isEmpty()) {
				clashMap = (Map<String, Map<String, Object>>)rehearseMap.get("clashMap");
			}else{
				rehearseMap = new HashMap<String, Object>();
				Map<String, Object> taskRouteMap = new HashMap<String, Object>();
				//根据方案获取线路列表信息
				if(schemeList != null && schemeList.size() > 0) {
					taskRouteMap = RouteHandleHelper.getRouteListByScheme(schemeList, this.getRouteInfoService());
					if(taskRouteMap != null && !taskRouteMap.isEmpty()) {
						minBeginLong = (long)taskRouteMap.get("minBeginLong");
						maxEndLong = (long)taskRouteMap.get("maxEndLong");
						taskRouteList = (List<Map<String, Object>>)taskRouteMap.get("taskRouteList");
					}else {
						return false;
					}
				}
				//long time4 = new Date().getTime();
				//执行线路按规定时间间隔进行拆分
				if(taskRouteList != null && taskRouteList.size() > 0) {
					//Map<String, Map<String, Map>> taskByTimeMap = RouteHandleHelper.routeInfoByTime(taskRouteList, routeSplitTime, false);
					Map<String, Map<String, Map>> taskByTimeMap = new HashMap<String, Map<String,Map>>();
					Vector<Thread> ts = new Vector<Thread>();
					for (Map<String, Object> taskRouteMapTemp : taskRouteList) {
						Thread t = new Thread(new Runnable() {
							@Override
							public void run() {
								RouteHandleHelper.routeInfoByTimeOne(taskByTimeMap, taskRouteMapTemp, routeSplitTime, false);
							}
						});
						ts.add(t);
						t.start();
					}
					for (Thread t : ts) {
						try {
							t.join();//等待所有线路拆分完成
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					
					//long time5 = new Date().getTime();
					if(taskByTimeMap != null && !taskByTimeMap.isEmpty()) {
						//根据线路分隔数据分析冲突情况
						clashMap =  RouteClashHelper.routeClashAnalysis(taskByTimeMap, taskRouteList, minBeginLong, maxEndLong, 
								routeSplitTime, timeNum, clashDistance, isDetail);
						
						//存入预测数据缓存
						if(isDetail) {
							rehearseMap.putAll(taskRouteMap);//线路信息
							rehearseMap.put("taskByTimeMap", taskByTimeMap);//线路拆分信息
							rehearseMap.put("clashMap", clashMap);//线路冲突信息
							RehearseGlobal.RehearseDataPool.put(poolKey, rehearseMap);
						}
					}
					//long time6 = new Date().getTime();
					//System.out.println(executeDate+"线路拆分时间"+ (time5 - time4) +"ms--冲突分析时间"+(time6 - time5)+"ms");
				}
			}
			boolean isClash = false;
			List<Map<String, Object>> clashInfoList = new ArrayList<Map<String, Object>>();
			if(clashMap != null && !clashMap.isEmpty()) {
				isClash = true;
				if(isDetail) {
					for (Map.Entry<String, Map<String, Object>> m : clashMap.entrySet()) {
						Map<String, Object> clashInfoMap = RouteClashHelper.getClashInfoByChange(m.getValue());
						clashInfoMap.put("clashId", m.getKey());
						clashInfoList.add(clashInfoMap);
					}
					//clashInfoList排序(根据冲突ID后面的时间戳);
					Collections.sort(clashInfoList, new Comparator<Map<String, Object>>() {
						/*
						 * int compare(Person p1, Person p2) 返回一个基本类型的整型， 返回负数表示：p1
						 * 小于p2， 返回0 表示：p1和p2相等， 返回正数表示：p1大于p2
						 */
						@Override
						public int compare(Map<String, Object> p1, Map<String, Object> p2) {
							String clashId1= ((String)p1.get("clashId")).split("_")[1];
							String clashId2= ((String)p2.get("clashId")).split("_")[1];
							if (Long.parseLong(clashId1) > Long.parseLong(clashId2)) {
								return 1;
							}
							if (Long.parseLong(clashId1) == Long.parseLong(clashId2)) {
								return 0;
							}
							return -1;
						}

					});
				}
			}
			jsonObject.put("executeDate", executeDate);
			jsonObject.put("isClash", isClash);
			jsonObject.put("clashContent", clashInfoList);
			this.getServerPushServiceImpl().pushMessage("" + browserId, jsonObject); // 推送冲突信息
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return false;
	}
}
